﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace MahaBaseWrapper.Core
{
    sealed class QueryProcessor<T> where T : class
    {
        #region Property

        private PropertyInfo[] _property;

        public PropertyInfo[] Property
        {
            get { return _property; }
            set { _property = value; }
        }

        private String[] _fields;

        public String[] Fields
        {
            get { return _fields; }
            set { _fields = value; }
        }

        private String[] _values;

        public String[] Values
        {
            get { return _values; }
            set { _values = value; }
        }

        private String _conditions;

        public String Conditions
        {
            get { return _conditions; }
            set { _conditions = value; }
        }

        private String _name;

        public String Name
        {
            get { return _name; }
            set { _name = value; }
        }

        #endregion

        public QueryProcessor()
        {
            this.Init();
        }

        private void Init()
        {
            this.Property = typeof(T).GetProperties();
            this.Name = typeof(T).Name;
            this.Fields = new String[this.Property.Length];

            for (int i = 0, z = this.Property.Length; i < z; i++)
            {
                this.Fields[i] = this.Property[i].Name;
            }
        }

        public void PerformDelete()
        {
            var query = new StringBuilder();
            query.Append("DELETE FROM " + Name + Conditions);

            DbHelper.SetProvider("System.Data.SqlClient");

            using (var connection = DbHelper.CreateConnection(WrapperConfiguration.Get().ConnectionString))
            {
                connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = query.ToString();
                    command.ExecuteNonQuery();
                }
            }
        }

        public void PerformInsert()
        {
            var query = new StringBuilder();
            query.Append("INSERT INTO " + Name + "(");

            for (int i = 0, z = Fields.Length; i < z; i++)
            {
                query.Append(Fields[i] + ",");
            }

            query = query.Remove(query.Length - 1, 1);
            query.Append(") VALUES (");

            for (int i = 0, z = Values.Length; i < z; i++)
            {
                query.Append(Values[i] + ",");    
            }

            query = query.Remove(query.Length - 1, 1);
            query.Append(")");    

            DbHelper.SetProvider("System.Data.SqlClient");

            using (var connection = DbHelper.CreateConnection(WrapperConfiguration.Get().ConnectionString))
            {
                connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = query.ToString();
                    command.ExecuteNonQuery();
                }
            }
        }

        public T PerformUpdate()
        {
            var query = new StringBuilder();
            query.Append("UPDATE " + Name + " SET ");

            for (int i = 0, z = Fields.Length; i < z; i++)
            {
                query.Append(Fields[i] + " = " + Values[i] + ",");
            }
            query = query.Remove(query.Length - 1, 1);
            query.Append(Conditions);


            DbHelper.SetProvider("System.Data.SqlClient");

            using (var connection = DbHelper.CreateConnection(WrapperConfiguration.Get().ConnectionString))
            {
                connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = query.ToString();
                    command.ExecuteNonQuery();
                }
            }
            
            var entity = Activator.CreateInstance<T>();

            for (int i = 0, z = Property.Length; i < z; i++)
            {
                Property[i].SetValue(entity, Values[i], null);
            }

            return entity;
        }

        public List<T> PerformSelectMany()
        {
            var list = Activator.CreateInstance<List<T>>();

            var query = new StringBuilder();
            query.Append("SELECT ");

            for (int i = 0, z = Fields.Length; i < z; i++)
            {
                query.Append(Fields[i] + ",");
            }
            query = query.Remove(query.Length - 1, 1);
            query.Append(" FROM ");
            query.Append(Name);
            query.Append(" " + Conditions + " ");


            DbHelper.SetProvider("System.Data.SqlClient");

            using (var connection = DbHelper.CreateConnection(WrapperConfiguration.Get().ConnectionString))
            {
                connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = query.ToString();

                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            var entity = Activator.CreateInstance<T>();

                            for (int i = 0, z = reader.FieldCount; i < z; i++)
                            {
                                Property[i].SetValue(entity, reader[i], null);
                            }

                            list.Add(entity);
                        }
                    }
                }
            }

            return list;
        }

        public T PerformSelectOne()
        {
            var entity = Activator.CreateInstance<T>();
            var query = new StringBuilder();
            query.Append("SELECT ");

            for (int i = 0, z = Fields.Length; i < z; i++)
            {
                query.Append(Fields[i] + ",");
            }
            query = query.Remove(query.Length - 1, 1);
            query.Append(" from ");
            query.Append(Name);
            query.Append(" " + Conditions + " ");


            DbHelper.SetProvider("System.Data.SqlClient");

            using (var connection = DbHelper.CreateConnection(WrapperConfiguration.Get().ConnectionString))
            {
                connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = query.ToString();

                    using (var reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            for (int i = 0, z = reader.FieldCount; i < z; i++)
                            {
                                Property[i].SetValue(entity, reader[i], null);
                            }
                        }
                    }
                }
            }
            return entity;
        }
    }
}